home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-68k-src / machines / amiga68k / libsrc / alib.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  16KB  |  550 lines

  1. /*
  2.  * ALIB Rev. 1.0
  3.  * Amiga Object Module Librarian
  4.  * Programmed by Mike Schwartz
  5.  *               (C)1985, MS Software, all rights reserved.
  6.  *
  7.  * Feel free to distribute this program on a no-charge basis.
  8.  *
  9.  * Use:
  10.  *    ALIB  option  library filelist
  11.  * Where
  12.  *    option may be one of the following:
  13.  *       D  =  delete object modules from library
  14.  *       R  =  replace object modules (or add if not defined)
  15.  *       L  =  directory of library
  16.  *    library is the name of the library file to be created or modified.
  17.  *       if no .lib extension is provided on the command line, it is
  18.  *       appended.  Also note that a file library.dir is created for
  19.  *       each library file and is managed by this program.
  20.  *    filelist is a list of object module filenames separated by spaces
  21.  *       or commas.  Note that if .o is not present in the filenames,
  22.  *       .o will be appended.
  23.  */
  24.  
  25.  
  26. /* This version of Alib has been modified, without permission, by
  27.  * Stephen Williams.  Changes are as follows:
  28.  *
  29.  * - .o is now not unconditionally added to object file names.  If the
  30.  *   extension is already present, no action is taken.  This appears to
  31.  *   be how the author wished Alib to behave (check out the online help)
  32.  *   but it never worked for me;
  33.  *
  34.  * - .lib may be added to the library name on the command line.  If it
  35.  *   isn't, it will be added.  .dir is handled fairly intelligently.
  36.  *   Again, the online help advertised this feature, although it never
  37.  *   worked;
  38.  *
  39.  * - Unix-style I/O (open(), close(), read() etc) has been replaced with
  40.  *   ANSI-style stdio streaming (fopen(), fclose(), fread() etc) to aid
  41.  *   portability, and generally make my life easier;
  42.  *
  43.  * - errors now go to stderr instead of stdout (I didn't bother marking
  44.  *   each individual change);
  45.  *
  46.  * - all files are written with permissions ----rw-d;
  47.  *
  48.  * - lots of little changes (marked where they have been made)
  49.  */
  50. static const char DOLLARVER[] = "\0$VER: Alib 1.0sw1 (11.3.98)";
  51.  
  52.  
  53. /* #include lines modified by Stephen Williams */
  54. #include <stdlib.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57.  
  58. #ifdef AMIGA
  59. #include <dos/dos.h>
  60. #include <clib/dos_protos.h>
  61. #include <inline/dos_protos.h>
  62. extern void * DOSBase;
  63. #endif
  64.  
  65.  
  66. /*
  67.  * The following structure defines the records in the .dir file for
  68.  * the library.
  69.  */
  70.  
  71. #define  LD    struct   libdir_def
  72. struct   libdir_def     {
  73.    char  object_filename[80];       /* name of .o file */
  74.    long  module_offset;             /* offset of module in .lib file */
  75.    long  module_size;               /* size of module in bytes */
  76.    };
  77.  
  78. /*
  79.  * When the library is openned, each object module is read into memory
  80.  * and managed with the following structure.
  81.  */
  82.  
  83. #define  LL    struct   liblist_def
  84. struct   liblist_def    {
  85.    struct   libdir_def  dir_entry;  /* directory entry for module */
  86.    char     *object_module;         /* actual text of module */
  87.    LL       *next;                  /* pointer to next in list */
  88.    };
  89.  
  90. /*
  91.  * +++ Change by Stephen Williams +++
  92.  *
  93.  * The original source here defined prototypes for external functions
  94.  * getmem() and lseek().  lseek() hasn't been used in my altered source;
  95.  * I replaced it with the stdio stream equivalent fseek().  getmem(),
  96.  * along with rlsmem(), is not defined anywhere in my includes, so I
  97.  * have provided macros to emulate these functions
  98.  */
  99.  
  100. #define    getmem(size)        (char *)calloc(size, 1)
  101. #define    rlsmem(pointer, size)    free(pointer)
  102.  
  103. /*
  104.  * +++ Addition by Stephen Williams +++
  105.  *
  106.  * The original source just strcat()ed a ".o" onto the end of all
  107.  * object file names.  This has been replaced with the following
  108.  * macro, which only adds .o if it isn't there already
  109.  */
  110.  
  111. #define makeobjname(s) if(strcmp((char *)(s + strlen(s) - 2), ".o")) strcat(s, ".o")
  112.  
  113. /*
  114.  * Global variables
  115.  *
  116.  * +++ Changes by Stephen Williams +++
  117.  *
  118.  * "int libfd", "int objfd" and "int dirfd" have become
  119.  * "FILE * libfp", "FILE * objfp" and "FILE * dirfp"
  120.  * to reflect the changes from Unix-style I/O to stdio streams
  121.  */
  122.  
  123. LL *    objlist=NULL;    /* linked list of object modules */
  124.  
  125. char    libname[80];    /* name of library file */
  126. FILE *    libfp;        /* file pointer for library file */
  127. char    objname[80];    /* name of object file */
  128. FILE *    objfp;        /* file pointer for object file */
  129. char    dirname[80];    /* name of directory file */
  130. FILE *    dirfp;        /* file pointer for directory file */
  131.  
  132. char  buf[512];                     /* misc buffer */
  133.  
  134. char  option;                       /* user selected option */
  135.  
  136.  
  137. /*
  138.  * This function prints the help messages and exits.
  139.  *
  140.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  141.  */
  142.  
  143. void help(void)
  144. {
  145.   /*
  146.    * +++ Changes by Stephen Williams +++
  147.    *
  148.    * - Multiple printf() statements merged into one;
  149.    * - Help text reworded
  150.    */
  151.    printf("Use:\n"
  152.           "   Alib D <library[.lib]> <object[.o]> [object[.o] ...]\n"
  153.           "   Alib R <library[.lib]> <object[.o]> [object[.o] ...]\n"
  154.           "   Alib L <library[.lib]>\n\n"
  155.           "Where\n"
  156.           "   D  =  delete object modules from library\n"
  157.           "   R  =  replace object modules (or add if not defined) \n"
  158.           "   L  =  directory of library\n\n"
  159.           "   Note that a file \"library.dir\" is created for each library file,\n"
  160.           "   and is managed by this program.  If \".lib\" and/or \".o\" suffixes\n"
  161.           "   are omitted on the command line, they will be added by the program.\n");
  162.  
  163.    exit(1);
  164. }
  165.  
  166.  
  167. /*
  168.  * The following function opens the library and directory file.  If the
  169.  * file does not exist, then the user is asked if he wants to create it.
  170.  * If the library exists, then it is read in and built in a linked list.
  171.  *
  172.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  173.  */
  174.  
  175. int open_library(void)
  176. {
  177.    LL    *lp;           /* pointer to module node */
  178.  
  179.    /*
  180.     * Open the library file and directory file.
  181.     * Changed by Stephen Williams to use stdio streams
  182.     *
  183.     */
  184.    libfp = fopen(libname, "r");
  185.    if (!libfp) {
  186.       /*
  187.        * Library does not exist, prompt user for creation.
  188.        */
  189.       while (1) {
  190.          printf("%s does not exist, create it? (Y/N): ", libname);
  191.          gets(buf);
  192.          if (buf[0] == 'y' || buf[0] == 'Y')
  193.             return !0;
  194.          if (buf[0] == 'n' || buf[0] == 'N') {
  195.             fprintf(stderr, "Alib abandoned\n");
  196.             exit(1);
  197.             }
  198.          }
  199.       }
  200.    dirfp = fopen(dirname, "r");
  201.    if (!dirfp) {
  202.       fprintf(stderr, "%s has been corrupted\n", dirname);
  203.       fprintf(stderr, "Alib abandoned\n");
  204.       exit(1);
  205.       }
  206.    /*
  207.     * library and directory files are open, read in the library.
  208.     */
  209.    while (1) {
  210.       /*
  211.        * Allocate a node to hold the object module.
  212.        */
  213.       lp = (LL *)getmem(sizeof(LL));
  214.       if (lp == NULL) {
  215.          fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
  216.          exit(1);
  217.          }
  218.       /*
  219.        * Check for end of file.
  220.        */
  221.       if (fread(&lp->dir_entry, sizeof(LD), 1, dirfp) != 1)
  222.          break;
  223.       /*
  224.        * Allocate a buffer to hold the object file image.
  225.        */
  226.       lp->object_module = getmem(lp->dir_entry.module_size);
  227.       if (lp->object_module == NULL) {
  228.          fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
  229.          exit(1);
  230.          }
  231.       /*
  232.        * Read in the object module
  233.        */
  234.       if (fread(lp->object_module, lp->dir_entry.module_size, 1, libfp) != 
  235.                                                                         1) {
  236.          fprintf(stderr, "Library file is corrupted.\nAlib abandoned\n");
  237.          exit(1);
  238.          }
  239.       /*
  240.        * Add module to linked list.
  241.        */
  242.       lp->next = objlist;
  243.       objlist = lp;
  244.       }
  245.    /*
  246.     * Library has been read in ok.  Close files and return.
  247.     */
  248.    fclose(libfp);
  249.    fclose(dirfp);
  250.    printf("Library file read in ok\n");
  251. }
  252.  
  253.  
  254. /*
  255.  * The following function removes an object module from the linked list
  256.  * and frees up any memory used by it.
  257.  *
  258.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  259.  */
  260.  
  261. int kill_module(char * name)
  262. {
  263.    LL    *lp;
  264.    LL    *lp2;
  265.  
  266.    if (objlist == NULL)
  267.       return 0;
  268.    strcpy(objname, name);
  269.    /*
  270.     * the next line changed from
  271.     * strcat(objname, ".o");
  272.     * by Stephen Williams
  273.     */
  274.    makeobjname(objname);
  275.    if (strcmp(objlist->dir_entry.object_filename,  objname) == 0) {
  276.         lp = objlist->next;
  277.         rlsmem(objlist->object_module, objlist->dir_entry.module_size);
  278.         rlsmem((char *)objlist, sizeof(LL));
  279.         objlist = lp;
  280.         return !0;
  281.    }
  282.    for (lp = objlist; lp->next != NULL; lp=lp->next)
  283.       if (strcmp(lp->next->dir_entry.object_filename, objname) == 0) {
  284.            lp2 = lp->next;
  285.            lp->next = lp2->next;
  286.            rlsmem(lp2->object_module, lp2->dir_entry.module_size);
  287.            rlsmem((char *)lp2, sizeof(LL));
  288.            return !0;
  289.       }
  290.    return 0;
  291. }
  292.  
  293.  
  294. /*
  295.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  296.  */
  297.  
  298. void add_module(char * name)
  299. {
  300.    LL    *lp;
  301.    int   len;
  302.  
  303.    strcpy(objname, name);
  304.    /*
  305.     * the next line changed from
  306.     * strcat(objname, ".o");
  307.     * by Stephen Williams
  308.     */
  309.    makeobjname(objname);
  310.    /* Initial \n in following printf() added by Stephen Williams */
  311.    printf("\nadding %s\n", objname);
  312.  
  313.    /*
  314.     * Open the object file
  315.     * Changed by Stephen Williams to use stdio streams
  316.     */
  317.    objfp = fopen(objname, "r");
  318.    if (!objfp) {
  319.       fprintf(stderr, "%s cannot be added\nAlib abandoned\n", objname);
  320.       exit(1);
  321.       }
  322.    /*
  323.     * Allocate a node to hold the file.
  324.     */
  325.    lp = (LL *)getmem(sizeof(LL));
  326.    if (lp == NULL) {
  327.       fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
  328.       exit(1);
  329.       }
  330.    /*
  331.     * Initialize it.
  332.     *
  333.     * Changes by Stephen Williams; the naughty author used absolute
  334.     * values for his lseek() modes; not SEEK_SET and SEEK_END.
  335.     * This was very very very silly.  Corrected
  336.     *
  337.     * Additional change; lseek() changed to fseek(), because I'm using
  338.     * stdio streams, not Unix file descriptors
  339.     */
  340.    strcpy(lp->dir_entry.object_filename, objname);
  341.    fseek(objfp, 0, SEEK_END);
  342.    lp->dir_entry.module_size = ftell(objfp);
  343.    /* %d in following printf() changed to %ld by Stephen Williams */
  344.    printf("module size = %ld\n", lp->dir_entry.module_size);
  345.    fseek(objfp, 0, SEEK_SET);
  346.    /*
  347.     * Allocate the buffer to read the object module into.
  348.     */
  349.    lp->object_module = getmem(lp->dir_entry.module_size);
  350.    if (lp->object_module == NULL) {
  351.       fprintf(stderr, "Not enough memory.\nAlib abandoned\n");
  352.       exit(1);
  353.       }
  354.    /*
  355.     * Read in the file.
  356.     */
  357.    if (fread(lp->object_module, lp->dir_entry.module_size, 1, objfp) != 1) {
  358.       fprintf(stderr, "Library file is corrupted.\nAlib abandoned\n");
  359.       exit(1);
  360.       }
  361.    /*
  362.     * Add module to linked list.
  363.     */
  364.    lp->next = objlist;
  365.    objlist = lp;
  366.    /*
  367.     * Close object file and return.
  368.     */
  369.    fclose(objfp);
  370.    printf("%s added\n", name);
  371. }
  372.  
  373.  
  374. /*
  375.  * The following routine writes the library from memory and exits.
  376.  *
  377.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  378.  */
  379.  
  380. void close_library(void) {
  381.    LL    *lp;
  382.    long  file_position;
  383.    long  length;
  384.  
  385.    /*
  386.     * Open the library
  387.     *
  388.     * +++ Changes by Stephen Williams +++
  389.     *
  390.     * All I/O changed from Unix-style to stdio streams;
  391.     *
  392.     * - Spelling mistake in error strings corrected; "openning"
  393.     *   changed to "opening"
  394.     *
  395.     */
  396.    libfp = fopen(libname, "w");
  397.    if (!libfp) {
  398.       fprintf(stderr, "Error opening %s for output\nAlib abandoned", libname);
  399.       exit(1);
  400.       }
  401.    dirfp = fopen(dirname, "w");
  402.    if (!dirfp) {
  403.       fprintf(stderr, "Error opening %s for output\nAlib abandoned", dirname);
  404.       exit(1);
  405.       }
  406.    /*
  407.     * Write out the individual modules and directory records.
  408.     */
  409.    file_position = 0;
  410.    for (lp = objlist; lp != NULL; lp = lp->next) {
  411.       length = 
  412.              fwrite(lp->object_module, 1, lp->dir_entry.module_size, libfp);
  413.       if (length != lp->dir_entry.module_size) {
  414.          fprintf(stderr, "Error writing to library file\nAlib abandoned\n");
  415.          exit(1);
  416.          }
  417.       lp->dir_entry.module_offset = file_position;
  418.       file_position += length;
  419.       if (fwrite((char *)&lp->dir_entry, sizeof(LD), 1, dirfp) != 1) {
  420.          fprintf(stderr, "Error writing to directory file\nAlib abandoned\n");
  421.          exit(1);
  422.          }
  423.       }
  424.    /*
  425.     * Close the library files
  426.     */
  427.    fclose(libfp);
  428.    fclose(dirfp);
  429.    /* the SetProtection() lines added by Stephen Williams */
  430.    #ifdef AMIGA
  431.    SetProtection(libname, FIBF_EXECUTE);
  432.    SetProtection(dirname, FIBF_EXECUTE);
  433.    #endif
  434.    /* the word "Library" in the following string capitalized by
  435.       Stephen Williams.  Initial \n also added */
  436.    printf("\nLibrary is %ld bytes\nAlib complete\n", file_position);
  437.    exit(0);
  438. }
  439.  
  440.  
  441. /*
  442.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  443.  *
  444.  * This function was below main(); moved above so main() sees a
  445.  * declaration for it
  446.  */
  447. void directory(void) {
  448.    LD    d_entry;
  449.    int   count;
  450.    int   bytes;
  451.  
  452.    /* Change by Stephen Williams: Unix I/O changed to stdio streams */
  453.    dirfp = fopen(dirname, "r");
  454.    if (!dirfp) {
  455.       fprintf(stderr, "%s not found\n", dirname);
  456.       exit(1);
  457.       }
  458.    printf("Directory of library %s\n", libname);
  459.    printf("Module Name                    Size   Offset\n");
  460.    count = bytes = 0;
  461.    while (fread((char *)&d_entry, sizeof(LD), 1, dirfp) == 1) {
  462.       /* %ds in following printf() changed to %lds by Stephen Williams */
  463.       printf("%-30.30s %-6ld %-6ld\n", d_entry.object_filename, 
  464.                d_entry.module_size, d_entry.module_offset);
  465.       count++;
  466.       bytes += d_entry.module_size;
  467.       }
  468.    printf("Library consists of %d entries totalling %d bytes\n", count,
  469.             bytes);
  470.    fclose(dirfp);
  471. }
  472.  
  473.  
  474. /*
  475.  * Main program.
  476.  *
  477.  * K&R-style function definition changed to ANSI-style by Stephen Williams
  478.  */
  479. int main(int argc, char * argv[])
  480. {
  481.    int   count;
  482.  
  483.    /*
  484.     * Banner changed by Stephen Williams to reflect the fact that the
  485.     * program has been hacked around
  486.     */
  487.    printf("Alib 1.0sw1\n"
  488.           "Amiga Object Module Librarian\n"
  489.           "Programmed by Mike Schwartz\n"
  490.           "Altered by Stephen Williams, without permission\n"
  491.           "(C)1985 MS Software, all rights reserved\n\n");
  492.  
  493.    /*
  494.     * check for command line parameters present.
  495.     */
  496.    if (argc < 3)
  497.       help();
  498.    /*
  499.     * setup the option and filenames
  500.     */
  501.    option = argv[1][0];
  502.    strcpy(libname, argv[2]);
  503.    strcpy(dirname, argv[2]);
  504.    /*
  505.     * start of major change by Stephen Williams
  506.     */
  507.    /* .lib extension present? */
  508.    if(!strcmp((char *)(libname + strlen(libname) - 4), ".lib"))
  509.      /* Yes; replace .lib with .dir in other name */
  510.      strcpy((char *)(dirname + strlen(dirname) - 3), "dir");
  511.    else {
  512.      /* Nope, gotta add it */
  513.      strcat(libname, ".lib");
  514.      strcat(dirname, ".dir");
  515.    }
  516.    /*
  517.     * end of change by Stephen Williams
  518.     */
  519.    if (option == 'l' || option == 'L') {
  520.       directory();
  521.       exit(0);
  522.       }
  523.    if (option != 'd' && option != 'D' && option != 'r' && option != 'R')
  524.       help();
  525.    /*
  526.     * Open the library file
  527.     */
  528.    open_library();
  529.    for (count = 3; count < argc; count++) {
  530.       switch(option) {
  531.          case 'd':
  532.          case 'D':
  533.             /* message format changed by Stephen Williams */
  534.             printf("\nDeleting %s from library...\n", argv[count]);
  535.             if (!kill_module(argv[count])) {
  536.                printf("failed\n");
  537.                fprintf(stderr, "%s not defined in library\n", argv[count]);
  538.             } else
  539.                printf("done\n");
  540.             break;
  541.          case 'r':
  542.          case 'R':
  543.             kill_module(argv[count]);
  544.             add_module(argv[count]);
  545.             break;
  546.          }
  547.       }
  548.    close_library();
  549. }
  550.